Apres l'installation, il est temps de programmer notre premier utilitaire avec Dice. La version enregistrée ayant beaucoup trops d'options pour utiliser les Alias comme pour la version FreeWare, nous allons donc créer un programme de configuration ... Il faut ce rappeler que DCC prend ces options aussi bien dans la ligne de commande que dans DCCOPTS. Attention : Il s'agit d'une variable de type COMMODORE ( donc stockée dans ENV: ), en opposition aux variables ARPssutilisées par CSH. Notre programme vas remplire cette variable en fonction de l'éxécutable que nous voulons créer. Tapper le listing de DiceConfig et compiller avec :
Dcc -2.0 -ms -// -r DiceConfig.c -o DiceConfig
DiceConfig a besoin d'un fichier de configuration nommé DiceConfig.cfg
-2.0 -ms -//
Math
-lm
La première ligne contient toutes les options toujours présentes ( -2.0 pour l'utilisation des includes et bibliothèques du 2.0, ... ). Les lignes suivantes indiquent, par groupes de 2, les librairies que l'on peut linker, la première ligne contenant le nom et la seconde les actions à faire.
A l'exécution, le programme ouvre une fenêtre ou l'on peut :
- Choisir le niveau de 'profilling'. Il s'agit de code que Dice rajoute et qui donne des statistiques sur l'exécution d'un programme. Tres utile pour savoir où un programme perd sont temps.
- Créer un programme 'pure' ( qui peut etre rendu resident ).
- Unix permet d'ouvir les fichiers avec une syntaxe à l' UNIX.
- Dynastack crée un programme avec une pile dynamique. Tres utile pour les programme recursif !
- Enfin Debug ajoute le hunk-symboles à l'éxécutable ( lors du réassemblage avec Dobj par exemples, les étiquettes sont conservées ). Il fait aussi un #define DEBUG pour une compilation conditionnelle. Nous y reviendrons par la suite ( Toujours des promesses ... ).
- Le dernier groupe de gadgets sert a choisir les bibliothèques à linker. Pour le moment, il ne devrait y avoir que 'math' de sélectionnable.
Regardons un peut le code : Il contient quelques particularité de Dice. D'abors, on peut voir que les messages peuvent être en français en mettant la variables Lang a 'Français'. Je prefere cette solution à la locale.library qui n'est pas compatible avec le 1.3 ( de toutes façon, je n'ai pas les docs ... ). La première chose qui peut surprendre les utilisateurs d'autres compilateurs, est que je n'ai ouvert aucunes librairies : Dice le fait tout seul. Celà évite quelques Gurus !! Une des fonctions de ce programme est aussi de se rappeller la config des gadgets entre 2 appels. J'ai donc utilisé la propriété __config pour 2 variables qui contiennent l'état du programme. Dice crée le code pour que ces variables soit automatiquement lues au départ et sauvegardées à la fin de l'exécution.
Grace à l'option -r, notre éxécutable peut être mis résident. Voila une bonne occasion pour ce pencher sur les programmes Pure...
Un programme pure est un programme qui peut être mis résident. Cette possibilité est apparue avec le WB 1.3 pour les utilisateurs du shell standard et depuis beaucoup plus longtemps pour ceux qui préfèrent les Shells utilisant l'Arp.library ( Csh, Ashell, ... ). Une fois de plus, grâce à Commodore, les deux résidents ne sont pas compatibles !! ( mais ils peuvent quand même cohabiter comme nous avons pu le voir dans le premier épisode ). Pour résumer, la table Commodore est gérée par 'Res1.3' alors que la table Arp est gérée par 'resident' (le resident du shell).Or Dcc se trouve dans l'Arp (pour être accessible depuis le Shell) et ne gère que la table Commodore où doit donc ce trouver Dc1,Das,Dlink . Les dernières versions de CSH ( V5.19 par exemple ) permettent d'utiliser aussi la tables Commodore mais ce n'est pas encore parfait ( & ça ne marche pas sous 2.0 ). Une autre différence, l'Arp reteste l'intégrité de la commande à chaque fois qu'il l'éxécute, mais pas Commodore. Essaillez de rendre résident une commande non-pure dans le shell du 1.3. La première exécution passe ... la seconde casse !! Csh nous aurais indiqué que la commande a été altéré . Quelles différences y a-t-il entre un programme ordinaire et une commande pure ? Un programme normal peut modifier ,comme il le veut, ces variables, voir son propre code, car à chaque nouvelle exécution, tous sera rechargé depuis le disque; Pour un programme résident, ceci n'est plus possible car le même segment mémoire est utilisé à chaque fois. Prenons le programme suivant :
int i=5;
Void main(){
i++;
printf("%d\n",i);
}
Dans le cas d'un programme non pure, le compilateur reservera la place pour i EN Y METTANT DIRECTEMENT LA VALEUR 5. Si ce programme est mis résident de force, la première exécution donnera 6 ( 5+1 ), mais la seconde donnera 7 ( 6+1 ) - ou ne marchera pas dans un shell Arp car le Check-sum de la commande a changé -. En effet, rien n'a remis i à sa valeur initiale après la première exécution ! Un programme pure s'y serait pris autrement : Les variables globales sont créées dynamiquement - ce qui permet à la commande de s'exécuter simultanément dans plusieurs shells, les variables étant recréees pour chaques taches - et son affectées ensuite à leurs valeurs initiales. Comment c'est pas claire ??? Allez prendre une bière - ou un Pastis - et relisez calmement ce qui pressède, ... De toutes facon, le C est un language de haut niveau, donc nous ne devrions pas nous soucier de ces questions très technique ... Ouai, bof, les utilisateurs du Lattice ou de l'Aztec peuvent vous en parler ( peut être que leurs dernières versions permettent ce genre de manipulations ). Avec Dice, rien de plus simple, il n'y a qu'a rajouter un -r à la ligne de commande et le tour est joué ... Presque, car si le programme comporte des données en chips, elles doivent obligatoirement être constantes. Enfin, Dice permet de partager des variables entre plusieurs taches d'un même programme s'il est résident, avec l'attribut __shared mais ca ne marche pas avec les shells Arp ( CheckSum modifier ).
Bon, c'est fini pour aujourd'hui. La prochaine fois les librairies partageables ...